﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Web;

namespace NH.Web.Common
{
    public class JSONPBehavior : Attribute, IOperationBehavior
    {
        public string Callback { get; set; }

        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
        {
            return;
        }

        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        {
            clientOperation.ParameterInspectors.Add(new Inspector(Callback));
        }

        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            dispatchOperation.ParameterInspectors.Add(new Inspector(Callback));
        }

        public void Validate(OperationDescription operationDescription)
        {
            return;
        }

        //Parameter inspector
        private class Inspector : IParameterInspector
        {
            private readonly string _callback;

            public Inspector(string callback)
            {
                _callback = callback;
            }

            public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
            {
            }

            public object BeforeCall(string operationName, object[] inputs)
            {
                string methodName = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters[_callback];
                if (methodName != null)
                {
                    var property = new JSONPMessageProperty
                    {
                        MethodName = methodName
                    };
                    OperationContext.Current.OutgoingMessageProperties.Add(JSONPMessageProperty.Name, property);
                }
                return null;
            }
        }
    }
}